import 'dart:convert';
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pointycastle/asymmetric/api.dart';
import 'package:pointycastle/export.dart' as pointycastle;

import '../core/logger.dart';

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

/// 加密工具类

import 'string_util.dart';

class EncryptUtils {
  EncryptUtils._internal();

  ///aes
  static String keyString = 'WmZq4t7w!z%C*F-J';
  static final encrypt.Key _keyAes = encrypt.Key.fromUtf8(keyString);
  static late encrypt.Encrypter _encryptAes;
  static String ivString = '7x!z%C*F-JaNdRgU';
  static final encrypt.IV _ivAes = encrypt.IV.fromUtf8(ivString);
  static const String sighKey = 's6v9y/B?E(H+MbQeThWmZq4t7w!z%C&F';

  ///rsa
  static late RSAPublicKey _publicKey;
  static late encrypt.Encrypter _encryptRsa;
  static late encrypt.Signer _signer;

  /// Rsa加密最大长度
  static const int MAX_ENCRYPT_BLOCK = 117;

  /// Rsa解密最大长度
  static const int MAX_DECRYPT_BLOCK = 128;

  static bool isInitRsa = false;

  ///初始化AES加密启动时调用
  static Future<void> initAes({
    encrypt.AESMode mode = encrypt.AESMode.cbc,
    String padding = 'PKCS7',
  }) async {
    _encryptAes =
        encrypt.Encrypter(encrypt.AES(_keyAes, mode: mode, padding: padding));
  }

  ///初始化RAS加密启动时调用
  static Future<void> initRsa(
      {required String publicKeyString, String? privatePath}) async {
    _publicKey = encrypt.RSAKeyParser().parse(publicKeyString) as RSAPublicKey;
    _encryptRsa = encrypt.Encrypter(
      encrypt.RSA(publicKey: _publicKey),
    );
    isInitRsa = true;
    _signer = encrypt.Signer(
        encrypt.RSASigner(encrypt.RSASignDigest.SHA256, publicKey: _publicKey));
    // await AppService.to.configureCoreKit();
  }

  ///Aes加密
  static String encryptAes(String content) {
    return _encryptAes.encrypt(content, iv: _ivAes).base64;
  }

  ///Aes加密
  static String encryptAes16Param(Map<String, dynamic> params) {
    params['sign'] = null;
    final List<String> keys = params.keys.toList()
      ..sort((String o1, String o2) => o1.compareTo(o2));
    // print(keys.toString());
    String sign = '';
    for (final String element in keys) {
      if (params[element] != null) {
        String eStr = '${params[element]}';
        if (eStr.contains('[') && eStr.contains(']') ||
            (eStr.contains('{') && eStr.contains('}'))) {
          eStr = eStr.replaceAll(' ', '');
        }
        sign += '$element=$eStr&';
      }
    }
    if (sign.length > 1) {
      sign = sign.substring(0, sign.length - 1);
    }

    final String md5Str = md5.convert(utf8.encode(sign)).toString();
    params['sign'] = md5Str;

    final Map<String, dynamic> encryptParams = <String, dynamic>{};
    for (final String element in keys) {
      encryptParams[element] = params[element];
    }
    final String paramJson = jsonEncode(encryptParams);
    final String encryptContent =
        _encryptAes.encrypt(paramJson, iv: _ivAes).base16.toUpperCase();
    return encryptContent;
  }

  static String rsaHeaderKey() {
    final Map<String, dynamic> headerBean = <String, dynamic>{
      'key': keyString,
      'iv': ivString
    };
    final String jsonStr = jsonEncode(headerBean);
    final String decrypted = encryptRsa(jsonStr);
    return decrypted;
  }

  static String aesHeaderValue(Map<String, dynamic> parameters) {
    final String encryptContent = _encryptAes
        .encrypt(jsonEncode(parameters), iv: _ivAes)
        .base16
        .toUpperCase();
    return encryptContent;
  }

  ///Aes解密
  static String decryptAes(String content) {
    return _encryptAes.decrypt(encrypt.Encrypted.fromBase64(content),
        iv: _ivAes);
  }

  ///Aes解密
  static String decryptAes16(String content) {
    // content =
    //     "DBE98F55E7C3C1BD5B14C21FB694BA8E46B1FE4C17172ECE70638650B7F2CCAC96BC39247251E27388F0611F877F754D60F0395A3DC809467B30C67800E685E7EA1A856B44606062917D4D17B91CE0CCA16BE7AA6FCC1AAB3603B95EFCA80D7F6F9543D1E5F17E7D0FE6E31AECAA544EC87D923C0B2A0D341238654C1304D1BC2704A0C35D2C31B6E398E111B5D5E5664C560B14A7227C5F998B2E6548FB6D77BF0906ED0B3860AB67F0D48375B9BAB138BEAFB79C0BE50481BE7EDAFAF7F72EC6924919043475DB8F96806D235913FF1588AE0CE66C146ED2298BE6F8CFA513B585D5E56BAEECC3A726A8209311FA8457DEBA98D34832547D4123A1749C75A0CF1370FF9AAC36F5BD27BB1F94F3741E8097CF654F4AA04CBB971092F07AE1FE6D3AE5447ED457906D5BD8077E7C6E9688F23A71D3FEF1F5C55790115B38D6474DFD7346D6F129FE8AA3FC3244B9998AE9F08F37D7E94EE45C2F8550A7D36BBFEFE0CA1318238E5B83A2F938691CAA546D799E786521AE4DD5FD3B7E27C75C172572CB28A43BD64C860B5B1EA7F52C3787A6285A4E0DD7A57F4E4DD3E1A9B51EE1FE09FAE6C457475A74A1F5AC0E1327B5AB73E41C539FF604CC8276493B25C407331943C233F9E54406F83D53C33FE665ED6DF287FA10AB48499E5D72F6EC9BCD2E00557F795DC7A3A4AB81531867D54C78CD91DFADC41B4667614BC0C35F1129C0757F1E9B1D8594DAD28534E53493A4516EB1A827C50FEEBEACC42C2A2A47EE15265EBD2AE5437D45EFB0AFF1EC86D822F99CCBD99122BD5F948337010ED154F962999DE5CFC7389F6FE2581BC8F72B015133A986E9902DEC1D74EEE069F67B601A3413FCE9CF75C5FA89F4D074233500503C887E9198C49B3F0A92BF3E0A";
    // content = "E3375A49634D21A49E65555F8080BDE4BB30DA4CF6F080F1216EE1A7FE9B90FC03D11399E48497177C0C234F20ECAC2FFD3E514F55F72A0A9448AF8951100BA81037F64C8600DC4709CA4A3E2F38DEE6D4D88723ADA5C7C676D85BEF1D2C010A6D3193A40530A78159B65DF8895CCF8EBFE183C4164264A72549528B8C8B7D13";
    final String decrypted = _encryptAes.decrypt16(content, iv: _ivAes);
    return decrypted;
  }

  ///公钥Rsa加密
  static String encryptRsa(String context) {
    // 原始字符串转成字节数组
    final List<int> sourceBytes = utf8.encode(context);
    // 数据长度
    final int inputLen = sourceBytes.length;
    // 缓存数组
    final List<int> cache = <int>[];
    // 分段加密 步长为MAX_ENCRYPT_BLOCK
    for (int i = 0; i < inputLen; i += MAX_ENCRYPT_BLOCK) {
      // 剩余长度
      final int endLen = inputLen - i;
      List<int> item;
      if (endLen > MAX_ENCRYPT_BLOCK) {
        item = sourceBytes.sublist(i, i + MAX_ENCRYPT_BLOCK);
      } else {
        item = sourceBytes.sublist(i, i + endLen);
      }
      // 加密后对象转换成数组存放到缓存
      cache.addAll(_encryptRsa.encryptBytes(item).bytes);
    }
    // 加密后数组转换成base64编码并返回
    final String en = base64.encode(cache);
    return en;
  }

  ///私钥Rsa解密
  static String decryptRsa(String data) {
    try {
      // 原始字符串转成字节数组
      final Uint8List sourceBytes = base64.decode(data);
      // 数据长度
      final int inputLen = sourceBytes.length;
      // 缓存数组
      final List<int> cache = <int>[];

      final pointycastle.PKCS1Encoding cipher = pointycastle.PKCS1Encoding(
          pointycastle.RSAEngine())
        ..init(
            false, pointycastle.PublicKeyParameter<RSAPublicKey>(_publicKey));
      // 分段解密 步长为MAX_DECRYPT_BLOCK
      for (int i = 0; i < inputLen; i += MAX_DECRYPT_BLOCK) {
        // 剩余长度
        final int endLen = inputLen - i;
        if (endLen > MAX_DECRYPT_BLOCK) {
          sourceBytes.sublist(i, i + MAX_DECRYPT_BLOCK);
        } else {
          sourceBytes.sublist(i, i + endLen);
        }
        // 解密后存放到缓存
        cache.insertAll(0, cipher.process(sourceBytes).cast<int>());
      }

      // 解密后数组解码并返回
      final String decode = String.fromCharCodes(cache);
      return decode;
    } catch (e, s) {
      CoreKitLogger().e('', e, s);
      return '';
    }
  }

  ///用私钥对信息生成数字签名
  static String sign(String data) {
    return _signer.sign(data).base64;
  }

  ///校验数字签名
  static bool verify(String data, String sign) {
    return _signer.verify64(data, sign);
  }

  ///通过头部的key密文和请求的数据 进行 解密
  static Map<String, dynamic>? decryptKeyAndResp(
      {required String keyEncrypt, required String respData}) {
    /// 测试数据开始
    // keyEncrypt =
    //     'Nj4EIH7lR01MLfkKQZEEFqanNbdXkDNVCB5KXpTX79lvAUiKpiBWmoWwkwBczMy9gIxZl46IB0m7R0ot3zrCRSSY63pPfOBSb8986CzSNAiT1ioYF0l21iJs5I/I/Dx/7z0k9ponWAS9cAahY6X8pnGzLikOBVVnCPAPtDBIjPs=';

    // respData =
    //     '93FC8153A29762C6C945A742F6089F682053AC75EF8F9C71FAE42887D0E7720691BBB191DFC439F4C25487D6EE425981B118C4C06859531C0F89D46CD3950C24BE85273F6464AAB3BD775AF1C3BE77283EC14CB4C879B9FB0136A4FEE49F6BC3C74AD7AAB674880964AD303B6DA567FEBF19E909C285AE4F9604B0FAD2E92FED6AAF13043BAAB303854B1D0856291ABF3429107BACA1C44F6B64A82F37B6A0C186736398DCD3D0CC06D1CF3A6A2309CB23B3294B14A5E5AEEA2BF5619FD15BCBBD7F927BDF7370A8E2BCD4A49CE1C011D1C5A1758A25D06E39DA19AA124DE553B2DF7764109192E021DB0E0F407810DC4A7C8B07BAC9D0C27BD545C4E2E08AE9';
    /// 测试数据结束

    final String resultString = decryptRsa(keyEncrypt);

    final Map<String, dynamic> aesKeyIv =
        jsonDecode(resultString) as Map<String, dynamic>;

    final encrypt.Key key = encrypt.Key.fromUtf8(aesKeyIv['key'].toString());
    final encrypt.IV iv = encrypt.IV.fromUtf8(aesKeyIv['iv'].toString());

    final encrypt.AES aes = encrypt.AES(key, mode: encrypt.AESMode.cbc);
    final encrypt.Encrypter aesEncrypt = encrypt.Encrypter(aes);

    final String decrypted = aesEncrypt.decrypt16(respData, iv: iv);
    if (jsonDecode(decrypted) is Map) {
      return jsonDecode(decrypted) as Map<String, dynamic>;
    }
    return null;
  }

  static Future<Map<String, dynamic>> commonHeader() async {
    final PackageInfo info = await PackageInfo.fromPlatform();
    final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
    final Map<String, dynamic> header = <String, dynamic>{};
    String? identifier;
    header['platform'] = 'android';
    if (!kIsWeb) {
      if (Platform.isAndroid) {
        final AndroidDeviceInfo build = await deviceInfoPlugin.androidInfo;
        //UUID for Android
        identifier = build.id;

        // header['platform'] = 'android';
      } else if (Platform.isIOS) {
        final IosDeviceInfo data = await deviceInfoPlugin.iosInfo;
        //UUID for ios
        identifier = data.identifierForVendor;
        // header['platform'] = 'ios';
      }

      // header['platform'] = 'android';
      header['identifier'] = identifier;
    } else {
      // header['platform'] = 'mobile';
      header['identifier'] = 42;
    }

    ///就算空都不能刪除？奇葩喲
    header['token'] = '';
    header['version'] = info.version;
    header['noncestr'] = generateRandomString(16);
    header['timestamp'] = DateTime.now().millisecondsSinceEpoch;
    return header;
  }

  static Future<Map<String, dynamic>> addCryptKey() async {
    final Map<String, dynamic> headers = await commonHeader();
    final Map<String, dynamic> parameters = <String, dynamic>{};

    // final LoginInfo info = AuthService.to.loginInfo.value;
    // if (info.token != null && info.token!.accessToken != null) {
    //   headers['token'] = info.token?.accessToken;
    //   parameters['Authorization'] =
    //       '${info.token?.tokenType} ${info.token?.accessToken}';
    // }

    final String key = EncryptUtils.rsaHeaderKey();
    final String value = EncryptUtils.aesHeaderValue(headers);

    parameters['key'] = key;
    parameters['value'] = value;
    parameters['debug'] = false;
    parameters['user-agent'] = 'Custom-UA';
    parameters['accept'] = 'application/json;charset=utf-8';
    parameters['accept-language'] = 'zh';
    parameters['accept-device'] = 'm';
    return parameters;
  }

  /// 通过加密前面的 base64 -> aes ->base64
  static Future<Uint8List?> decodeImg(
      {required String data, String? keyIv}) async {
    // if (AppPolicies.fileEncryptKey == null ||
    //     AppPolicies.fileEncryptIv == null) {
    //   CoreKitLogger().e('file_encrypt_iv 或者 file_encrypt_iv 空了没使用获取秘钥接口');
    //   return null;
    // }

    try {
      // final encrypt.Key key = encrypt.Key.fromUtf8(AppPolicies.fileEncryptKey!);
      // encrypt.IV iv;
      //
      // final encrypt.AES aes = encrypt.AES(key, mode: encrypt.AESMode.cbc);
      // final encrypt.Encrypter aesEncrypt = encrypt.Encrypter(aes);
      //
      // Map<String, dynamic> decodeData = <String, dynamic>{};
      //
      // if (keyIv != null) {
      //   ///得到相应内容
      //   decodeData =
      //       EncryptUtils.decryptKeyAndResp(keyEncrypt: keyIv, respData: data) ??
      //           <String, dynamic>{};
      // }
      // final Map<String, dynamic> img =
      //     decodeData['data'] as Map<String, dynamic>;
      //
      // final String imgData = img['avatar_encrypt'].toString();
      //
      // if (imgData.isEmpty) {
      //   return null;
      // }
      //
      // iv = encrypt.IV.fromUtf8(AppPolicies.fileEncryptIv!);
      // final String decrypted = aesEncrypt.decrypt64(imgData, iv: iv);
      // final Uint8List uint8List = base64.decode(decrypted);
      // return uint8List;
    } catch (e, s) {
      CoreKitLogger().e('decodeImg', e, s);
      return null;
    }
  }
}
